home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
mail
/
delivery
/
smail-3.1
/
smail-3
Wrap
Text File
|
1994-12-13
|
13KB
|
437 lines
--- src/smtprecv.c 1994/11/30 08:44:04 1.2
+++ src/smtprecv.c 1994/11/30 15:10:34 1.3
@@ -1,4 +1,4 @@
-/* @(#) $Id: smtprecv.c,v 1.2 1994/11/30 08:44:04 logiciel Exp $ */
+/* @(#) $Id: smtprecv.c,v 1.3 1994/11/30 15:10:34 logiciel Exp $ */
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
@@ -279,7 +279,9 @@
if (out) {
fprintf(out, "250-%s Hello %s, here's what we support:\r\n",
primary_name, data);
+#ifndef NO_VERIFY
fprintf(out, "250-EXPN\r\n");
+#endif
#ifdef HAVE_DF_SPOOL
accepted_msg_size = compute_max_message_size_from_df_spool ();
if (accepted_msg_size == -1
--- src/transports/smtplib.c 1994/11/30 08:58:18 1.2
+++ src/transports/smtplib.c 1994/12/13 11:39:28 1.5
@@ -1,4 +1,4 @@
-/* @(#) $Id: smtplib.c,v 1.2 1994/11/30 08:58:18 logiciel Exp $ */
+/* @(#) $Id: smtplib.c,v 1.5 1994/12/13 11:39:28 logiciel Exp $ */
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
@@ -52,8 +52,10 @@
#define DATA "DATA"
#define DATA_END "."
#define QUIT "QUIT"
+#define VERB "VERB"
/* reply code groups, encoded in hex */
+#define POSITIVE_DEBUG 0x000 /* debugging messages */
#define POSITIVE_PRELIM 0x100 /* positive preliminary replies */
#define POSITIVE_COMPLETE 0x200 /* positive completion replies */
#define POSITIVE_INTERMEDIATE 0x300 /* positive intermediate replies */
@@ -84,7 +86,7 @@
/* functions local to this file */
#ifdef __STDC__
-extern int smtp_startup(struct smtp *, struct error **);
+extern int smtp_startup(struct smtp *, struct error **, int);
extern int smtp_send(struct smtp *, struct addr *, struct addr **, struct addr **, struct addr **, struct error **);
extern void smtp_shutdown(struct smtp *);
static void do_smtp_shutdown(struct smtp *, int);
@@ -130,17 +132,25 @@
* the session for future mail commands. Once the startup has been
* acomplished, smtp_send() can be used to send individual messages.
*
+ * If try_ehlo is non-zero and ESMTP support is configured, perform
+ * ESMTP negotiaition using the EHLO greeting command.
+ *
* return:
* SMTP_SUCCEED on successful startup
* SMTP_FAIL if the connection should not be retried
* SMTP_AGAIN if the connection should be retried later
+ * SMTP_EHLO_FAIL if the receiver hung up in response
+ * to an EHLO command. This can only occur when
+ * try_ehlo is set.
*
- * For SMTP_FAIL and SMTP_AGAIN, return a filled-in error structure.
+ * For SMTP_FAIL and SMTP_AGAIN (but not SMTP_EHLO_FAIL), return a
+ * filled-in error structure.
*/
int
-smtp_startup(smtpb, error_p)
+smtp_startup(smtpb, error_p, try_ehlo)
struct smtp *smtpb; /* SMTP description block */
struct error **error_p; /* error description */
+ int try_ehlo; /* whether to use ESMTP */
{
int reply;
char *reply_text;
@@ -171,101 +181,133 @@
}
#ifdef HAVE_EHLO
- /*
- * say who we are.
- * Possible responses:
- * 250 - okay (continue conversation)
- * 421 - closing down (try again later)
- * 5xx - fatal error (try HELO)
- */
- smtp_out.i = 0;
- (void) str_printf(&smtp_out, EHLO(primary_name));
+ if (try_ehlo) {
+ /*
+ * say who we are.
+ * Possible responses:
+ * 250 - okay (continue conversation)
+ * 421 - closing down (try again later)
+ * 5xx - fatal error (try HELO)
+ */
+ smtp_out.i = 0;
+ (void) str_printf(&smtp_out, EHLO(primary_name));
- reply = wait_write_command(smtpb, smtpb->short_timeout,
- smtp_out.p, smtp_out.i, &reply_text);
+ reply = wait_write_command(smtpb, smtpb->short_timeout,
+ smtp_out.p, smtp_out.i, &reply_text);
- if (REPLY_GROUP(reply) == NEGATIVE_TRY_AGAIN) {
- /* remote SMTP closed, try again later */
- *error_p = try_again(smtpb->tp, reply_text);
- return SMTP_AGAIN;
- }
- if (reply == REPLY_OK) {
- char * cp = reply_text;
- int on_greet_line = 1;
-
- smtpb->smtp_flags = ESMTP_basic;
- /* Parse the EHLO reply to find out
- what the remote server supports */
- while (*cp != 0) {
- int skip;
- int keywordlength;
-
- for (skip = 4; *cp != 0 && skip; --skip, ++cp) {
- if (skip == 1
- ? (*cp != ' ' && *cp != '-')
- : (! isdigit (*cp))) {
+ if (reply == REPLY_TIMEOUT) {
+ /* Some gateways just terminate the conection when they
+ receive an EHLO. We handle this case by returning a
+ special value here. Also write a message to the log
+ file because it is interesting to know which mailers
+ expose this problem. */
+ write_log(LOG_SYS, "link broken by EHLO!");
+ return SMTP_EHLO_FAIL;
+ }
+ if (REPLY_GROUP(reply) == NEGATIVE_TRY_AGAIN) {
+ /* remote SMTP closed, try again later */
+ *error_p = try_again(smtpb->tp, reply_text);
+ return SMTP_AGAIN;
+ }
+ if (reply == REPLY_OK) {
+ char * cp = reply_text;
+ int on_greet_line = 1;
+
+ smtpb->smtp_flags = ESMTP_basic;
+ /* Parse the EHLO reply to find out
+ what the remote server supports */
+ while (*cp != 0) {
+ int skip;
+ int keywordlength;
+
+ for (skip = 4; *cp != 0 && skip; --skip, ++cp) {
+ if (skip == 1
+ ? (*cp != ' ' && *cp != '-')
+ : (! isdigit (*cp))) {
+ goto malformed_ehlo_reply;
+ }
+ }
+ if (skip != 0) {
goto malformed_ehlo_reply;
}
- }
- if (skip != 0) {
- goto malformed_ehlo_reply;
- }
- if (on_greet_line) {
- /*
- * Ignore greeting on first line
- */
- on_greet_line = 0;
- goto skip_rest_of_line;
- }
- for (keywordlength = 0;
- *(cp+keywordlength) != 0
- && !isspace (*(cp+keywordlength));
- ++keywordlength)
- ;
- if (strncmpic(cp, "SIZE", keywordlength) == 0) {
- unsigned long max_size = 0;
-
- cp += keywordlength;
- while (*cp == ' ' || *cp == '\t')
- ++cp;
- if (!isdigit(*cp) && *cp != '\n')
- goto malformed_ehlo_reply;
- while (isdigit(*cp)) {
- max_size *= 10;
- max_size += *cp - '0';
- ++cp;
+ if (on_greet_line) {
+ /*
+ * Ignore greeting on first line
+ */
+ on_greet_line = 0;
+ goto skip_rest_of_line;
}
- smtpb->smtp_flags |= ESMTP_size;
- smtpb->max_size = max_size;
- } else if (strncmpic(cp, "8BITMIME", keywordlength) == 0) {
- smtpb->smtp_flags |= ESMTP_8bitmime;
- } else if (strncmpic(cp, "PIPELINING", keywordlength) == 0) {
- smtpb->smtp_flags |= ESMTP_pipelining;
- } else {
+ for (keywordlength = 0;
+ *(cp+keywordlength) != 0
+ && !isspace (*(cp+keywordlength));
+ ++keywordlength)
+ ;
+ if (strncmpic(cp, "SIZE", keywordlength) == 0) {
+ unsigned long max_size = 0;
+
+ cp += keywordlength;
+ while (*cp == ' ' || *cp == '\t')
+ ++cp;
+ if (!isdigit(*cp) && *cp != '\n')
+ goto malformed_ehlo_reply;
+ while (isdigit(*cp)) {
+ max_size *= 10;
+ max_size += *cp - '0';
+ ++cp;
+ }
+ smtpb->smtp_flags |= ESMTP_size;
+ smtpb->max_size = max_size;
+ } else if (strncmpic(cp, "8BITMIME", keywordlength) == 0) {
+ smtpb->smtp_flags |= ESMTP_8bitmime;
+ } else if (strncmpic(cp, "PIPELINING", keywordlength) == 0) {
+ smtpb->smtp_flags |= ESMTP_pipelining;
+ } else if (strncmpic(cp, "XVRB", keywordlength) == 0) {
+ smtpb->smtp_flags |= ESMTP_verbose;
+ } else if (strncmpic(cp, "XONE", keywordlength) == 0) {
+ smtpb->smtp_flags |= ESMTP_one;
+ } else if (strncmpic(cp, "XQUE", keywordlength) == 0) {
+ smtpb->smtp_flags |= ESMTP_queue;
+ } else {
+ }
+ skip_rest_of_line:
+ while (*cp != 0 && *cp != '\n')
+ ++cp;
+ if (*cp == '\n')
+ ++cp;
}
- skip_rest_of_line:
- while (*cp != 0 && *cp != '\n')
- ++cp;
- if (*cp == '\n')
- ++cp;
- }
#ifndef NO_LOG_EHLO
- write_log(LOG_SYS, "destination supports esmtp%s%s%s",
- smtpb->smtp_flags & ESMTP_8bitmime ? " 8BITMIME" : "",
- smtpb->smtp_flags & ESMTP_size ? " SIZE" : "",
- smtpb->smtp_flags & ESMTP_pipelining ? " PIPELINING" : "");
+ write_log(LOG_SYS, "destination supports esmtp%s%s%s%s%s%s",
+ smtpb->smtp_flags & ESMTP_8bitmime ? " 8BITMIME" : "",
+ smtpb->smtp_flags & ESMTP_size ? " SIZE" : "",
+ smtpb->smtp_flags & ESMTP_pipelining ? " PIPELINING" : "",
+ smtpb->smtp_flags & ESMTP_verbose ? " XVRB" : "",
+ smtpb->smtp_flags & ESMTP_one ? " XONE" : "",
+ smtpb->smtp_flags & ESMTP_queue ? " XQUE" : "");
#endif /* not NO_LOG_EHLO */
- return SMTP_SUCCEED;
- malformed_ehlo_reply:
- /* This seems to be a reasonable way
- to handle malformed EHLO replies: */
+ if (smtpb->smtp_flags & ESMTP_verbose
+ && debug >= DBG_DRIVER_MID) {
+ smtp_out.i = 0;
+ (void) str_printf(&smtp_out, VERB);
+ reply = wait_write_command(smtpb, smtpb->short_timeout,
+ smtp_out.p, smtp_out.i, &reply_text);
+ if (REPLY_GROUP (reply) == NEGATIVE_TRY_AGAIN) {
+ /* remote SMTP closed, try again later */
+ *error_p = try_again(smtpb->tp, reply_text);
+ return SMTP_AGAIN;
+ }
+ }
+ return SMTP_SUCCEED;
+ malformed_ehlo_reply:
+ /* This seems to be a reasonable way
+ to handle malformed EHLO replies: */
#ifndef NO_LOG_EHLO
- write_log(LOG_SYS, "destination supports esmtp, but is buggy (%s)",
- reply_text);
+ write_log(LOG_SYS, "destination supports esmtp, but is buggy (%s)",
+ reply_text);
#endif /* not NO_LOG_EHLO */
- return SMTP_SUCCEED;
+ return SMTP_SUCCEED;
+ }
}
-#endif
+#endif /* HAVE_EHLO */
/*
* say who we are.
* Possible responses:
@@ -755,8 +797,12 @@
if (! smtpb->in) {
return REPLY_OK;
}
- result = read_response_internal (smtpb, timeout, reply_text);
- DEBUG1(DBG_DRIVER_MID, "SMTP-reply: %s\n", *reply_text);
+ do
+ {
+ result = read_response_internal (smtpb, timeout, reply_text);
+ DEBUG1(DBG_DRIVER_MID, "SMTP-reply: %s\n", *reply_text);
+ }
+ while (REPLY_GROUP (result) == POSITIVE_DEBUG);
return result;
}
--- src/transports/smtplib.h 1994/11/30 08:59:35 1.2
+++ src/transports/smtplib.h 1994/12/13 10:59:53 1.4
@@ -1,4 +1,4 @@
-/* @(#) $Id: smtplib.h,v 1.2 1994/11/30 08:59:35 logiciel Exp $ */
+/* @(#) $Id: smtplib.h,v 1.4 1994/12/13 10:59:53 logiciel Exp $ */
/*
* Copyright (C) 1987, 1988 by Ronald S. Karr and Landon Curt Noll
@@ -17,6 +17,7 @@
#define SMTP_SUCCEED 0
#define SMTP_FAIL (-1)
#define SMTP_AGAIN (-2)
+#define SMTP_EHLO_FAIL (-3)
typedef enum
{
@@ -24,7 +25,10 @@
ESMTP_basic = 0x0001,
ESMTP_8bitmime = 0x0002,
ESMTP_size = 0x0004,
- ESMTP_pipelining = 0x0008
+ ESMTP_pipelining = 0x0008,
+ ESMTP_verbose = 0x0010,
+ ESMTP_one = 0x0020,
+ ESMTP_queue = 0x0040
}
SMTPExtension, SMTPExtensionFlags;
--- src/transports/tcpsmtp.c 1994/11/30 09:04:54 1.2
+++ src/transports/tcpsmtp.c 1994/12/13 11:41:04 1.3
@@ -288,6 +288,7 @@
char *error_text;
int success;
struct addr *ap;
+ int try_ehlo;
priv = (struct tcpsmtp_private *)tp->private;
@@ -310,43 +311,53 @@
/* reach out and touch someone */
- s = tcpsmtp_connect(hostname, ipaddr, family, service, &error_text);
- if (s >= 0) {
- s2 = dup(s);
- if (s2 < 0) {
- (void) close(s);
- s = -1;
- }
- }
- if (s < 0) {
- *ep = connect_failure(tp, error_text);
- return SMTP_AGAIN;
- }
-
- smtpbuf.in = fdopen(s, "r");
- smtpbuf.out = fdopen(s2, "w");
- smtpbuf.short_timeout = priv->short_timeout;
- smtpbuf.long_timeout = priv->long_timeout;
- smtpbuf.nl = "\r\n";
- tp->flags |= PUT_CRLF;
- smtpbuf.tp = tp;
- smtpbuf.smtp_flags = ESMTP_none;
- smtpbuf.max_size = 0;
-
- DEBUG(DBG_DRIVER_LO, "connected\n");
-
- switch (smtp_startup(&smtpbuf, ep)) {
-
- case SMTP_FAIL:
- insert_addr_list(addr, fail, *ep);
- (void) fclose(smtpbuf.in);
- (void) fclose(smtpbuf.out);
- return SMTP_FAIL;
-
- case SMTP_AGAIN:
- (void) fclose(smtpbuf.in);
- (void) fclose(smtpbuf.out);
- return SMTP_AGAIN;
+ for (try_ehlo = 1, success = 0; !success && try_ehlo >= 0; --try_ehlo) {
+ s = tcpsmtp_connect(hostname, ipaddr, family, service, &error_text);
+ if (s >= 0) {
+ s2 = dup(s);
+ if (s2 < 0) {
+ (void) close(s);
+ s = -1;
+ }
+ }
+ if (s < 0) {
+ *ep = connect_failure(tp, error_text);
+ return SMTP_AGAIN;
+ }
+
+ smtpbuf.in = fdopen(s, "r");
+ smtpbuf.out = fdopen(s2, "w");
+ smtpbuf.short_timeout = priv->short_timeout;
+ smtpbuf.long_timeout = priv->long_timeout;
+ smtpbuf.nl = "\r\n";
+ tp->flags |= PUT_CRLF;
+ smtpbuf.tp = tp;
+ smtpbuf.smtp_flags = ESMTP_none;
+ smtpbuf.max_size = 0;
+
+ DEBUG(DBG_DRIVER_LO, "connected\n");
+
+ switch (smtp_startup(&smtpbuf, ep, try_ehlo)) {
+
+ case SMTP_FAIL:
+ insert_addr_list(addr, fail, *ep);
+ (void) fclose(smtpbuf.in);
+ (void) fclose(smtpbuf.out);
+ return SMTP_FAIL;
+
+ case SMTP_AGAIN:
+ (void) fclose(smtpbuf.in);
+ (void) fclose(smtpbuf.out);
+ return SMTP_AGAIN;
+
+ case SMTP_EHLO_FAIL:
+ (void) fclose(smtpbuf.in);
+ (void) fclose(smtpbuf.out);
+ break;
+
+ default:
+ success = 1;
+ }
}
if (dont_deliver) {